﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
using HtmlParser.SiteManager;

namespace SmartCollector.HtmlParser.Utilities
{
    public class SerializeHelper
    {
        #region Constants
        const string SITE_COLLECTIONS = "SiteCollections";
        const string SITE_ELEMENT = "SiteElement";
        const string SITE_ID = "SiteId";
        const string SITE_NAME = "SiteName";
        const string ELEMENT_CONSTRAINT = "CollectionConstraints";
        const string TAG_CONSTRAINT = "Constraints";
        const string VALUES = "values";
        const string JOIN = ";";
        const char C_JOIN = ';';
        #endregion

        private static IEnumerable<string> s_regionCollections = Enum.GetNames(typeof(RegionArea));

        /// <summary>
        /// Gets or sets the deserialize structure.
        /// </summary>
        /// <value>
        /// The deserialize structure.
        /// </value>
        public static List<SiteItemStructure> DeserializeStructure(string filename)
        {
            List<SiteItemStructure> rs = new List<SiteItemStructure>();
            XmlTextReader reader = null;
            try
            {
                SiteItemStructure item = null;
                reader = new XmlTextReader(filename);
                while (reader.Read())
                {
                    if (reader.NodeType == XmlNodeType.Element)
                    {
                        switch (reader.Name)
                        {
                            case SITE_ELEMENT:
                                item = new SiteItemStructure();
                                item.SiteId = Int32.Parse(reader.GetAttribute(SITE_ID));
                                item.SiteDomainName = reader.GetAttribute(SITE_NAME);
                                break;
                            default:
                                if (s_regionCollections.Contains(reader.Name))
                                {
                                    string attributes = reader.GetAttribute(VALUES);
                                    string[] attributeArr = attributes.Split(C_JOIN);
                                    RegionArea region = (RegionArea) Enum.Parse(typeof(RegionArea),reader.Name);
                                    foreach (var tmp in attributeArr)
                                    {
                                        int index = tmp.IndexOf(":");
                                        item.AddConstraint(region, tmp.Substring(0, index),
                                            tmp.Substring(index +1, tmp.Length - index-1));
                                    }
                                }
                                break;
                        }
                    }
                    else if(reader.NodeType == XmlNodeType.EndElement 
                        && reader.Name == SITE_ELEMENT)
                    {
                        rs.Add(item);
                    }
                }
            }
            finally
            {
                if (reader != null)
                {
                    reader.Close();
                }
            }
            return rs;
        }

        /// <summary>
        /// Serializes the site structure.
        /// </summary>
        /// <param name="items">The items.</param>
        /// <param name="fileName">Name of the file.</param>
        public static void SerializeSiteStructure(IEnumerable<SiteItemStructure> items, string fileName)
        {
            XmlTextWriter writer = null;
            try
            {
                writer = new XmlTextWriter(fileName, Encoding.UTF8);
                writer.Formatting = Formatting.Indented;
                writer.WriteStartDocument();
                writer.WriteStartElement(SITE_COLLECTIONS);
                foreach (var item in items)
                {
                    writer.WriteStartElement(SITE_ELEMENT);
                    writer.WriteAttributeString(SITE_ID, item.SiteId.ToString());
                    writer.WriteAttributeString(SITE_NAME, item.SiteDomainName);

                    writer.WriteStartElement(ELEMENT_CONSTRAINT);
                    foreach (var tagSelector in item.ConstraintCollections)
                    {
                        writer.WriteStartElement(tagSelector.Key.ToString());
                        IList<string> details = new List<string>(tagSelector.Value.ConstraintCollections.Count);
                        foreach (var constraint in tagSelector.Value.ConstraintCollections)
                        {
                            details.Add(string.Format("{0}:{1}",constraint.Key, constraint.Value));
                        }
                        writer.WriteAttributeString(VALUES, string.Join(JOIN, details.ToArray()));
                        writer.WriteEndElement();
                    }
                    writer.WriteEndElement();
                    writer.WriteEndElement();
                }
                writer.WriteEndElement();
            }
            finally
            {
                if (writer != null)
                {
                    writer.Close();
                }
            }
        }

        /// <summary>
        /// Deserializes the specified item.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="item">The item.</param>
        /// <param name="fileName">Name of the file.</param>
        public static void Serialize<T>(T item, string fileName)
        {
            XmlWriter writer = null;
            try
            {
                writer = XmlWriter.Create(fileName, new XmlWriterSettings()
                {
                    Indent = true,
                    Encoding = Encoding.Unicode
                });
                XmlSerializer ser = new XmlSerializer(typeof(T));
                ser.Serialize(writer, item);
            }
            finally
            {
                if (writer != null)
                {
                    writer.Close();
                }
            }
        }

        /// <summary>
        /// Des the serialize.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="item">The item.</param>
        /// <param name="fileName">Name of the file.</param>
        public static T DeSerialize<T>(string fileName)
        {
            TextReader reader = null;
            T rs;
            try
            {
                XmlSerializer serializer = new XmlSerializer(typeof(T));
                reader = new StreamReader(fileName);
                rs = (T)serializer.Deserialize(reader);

            }
            finally
            {
                if (reader != null)
                {
                    reader.Close();
                }
            }
            return rs;
        }
    }
}
